package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

// ===== 配置常量 =====
const (
	endpoint          = "http://58.49.94.131:18380"          // MinIO 服务地址
	accessKeyID       = "yangmf"                             // MinIO Access Key
	secretAccessKey   = "159357aa"                           // MinIO Secret Key
	region            = "us-east-1"                          // MinIO 一般随便填，比如 us-east-1
	bucketName        = "ephpre"                             // Bucket 名称
	localUploadPath   = "D:\\raw\\logo.png"                  // 本地待上传文件路径
	localDownloadPath = "D:\\downloads\\logo-downloaded.png" // 下载后的本地路径
	objectKey         = "logo.png"                           // MinIO 中存储的对象键（即文件名）
)

var (
	s3Client *s3.Client
)

// ===== 初始化 S3 客户端（推荐方式：使用 EndpointResolverV2）=====
func initS3Client() error {
	// 1. 先加载默认配置（比如 region），但不设置全局 endpoint
	cfg, err := config.LoadDefaultConfig(context.TODO(),
		config.WithRegion(region),
	)
	if err != nil {
		return fmt.Errorf("加载默认配置失败: %v", err)
	}

	// 2. 创建 S3 客户端，并通过 EndpointResolverV2 设置 MinIO 的 endpoint 和认证信息
	s3Client = s3.NewFromConfig(cfg, func(o *s3.Options) {
		// 适配新版本的 EndpointResolver 接口
		o.EndpointResolver = s3.EndpointResolverFunc(func(region string, options s3.EndpointResolverOptions) (aws.Endpoint, error) {
			return aws.Endpoint{
				URL:           endpoint,
				PartitionID:   "aws",
				SigningRegion: region,
			}, nil
		})

		// 设置 MinIO 的 Access Key 和 Secret Key
		o.Credentials = aws.CredentialsProviderFunc(func(ctx context.Context) (aws.Credentials, error) {
			return aws.Credentials{
				AccessKeyID:     accessKeyID,
				SecretAccessKey: secretAccessKey,
				Source:          "Static credentials from code",
			}, nil
		})

		// MinIO 通常使用 Path Style（尤其是通过 IP 访问时）
		o.UsePathStyle = true
	})

	return nil
}

// ===== 上传文件到 MinIO =====
func uploadFile() error {
	file, err := os.Open(localUploadPath)
	if err != nil {
		return fmt.Errorf("无法打开本地文件 %s: %v", localUploadPath, err)
	}
	defer file.Close()

	_, err = s3Client.PutObject(context.TODO(), &s3.PutObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
		Body:   file,
	})
	if err != nil {
		return fmt.Errorf("上传文件失败: %v", err)
	}

	fmt.Printf("✅ 文件上传成功: %s/%s\n", bucketName, objectKey)
	return nil
}

// ===== 下载文件从 MinIO =====
func downloadFile() error {
	// 确保下载目录存在
	if err := os.MkdirAll(filepath.Dir(localDownloadPath), os.ModePerm); err != nil {
		return fmt.Errorf("无法创建下载目录: %v", err)
	}

	outFile, err := os.Create(localDownloadPath)
	if err != nil {
		return fmt.Errorf("无法创建下载文件 %s: %v", localDownloadPath, err)
	}
	defer outFile.Close()

	result, err := s3Client.GetObject(context.TODO(), &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		return fmt.Errorf("下载文件失败: %v", err)
	}
	defer result.Body.Close()

	_, err = outFile.ReadFrom(result.Body)
	if err != nil {
		return fmt.Errorf("写入下载文件失败: %v", err)
	}

	fmt.Printf("✅ 文件下载成功: %s -> %s\n", objectKey, localDownloadPath)
	return nil
}

// ===== 删除 MinIO 中的文件 =====
func deleteFile() error {
	_, err := s3Client.DeleteObject(context.TODO(), &s3.DeleteObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(objectKey),
	})
	if err != nil {
		return fmt.Errorf("删除文件失败: %v", err)
	}

	fmt.Printf("✅ 文件删除成功: %s/%s\n", bucketName, objectKey)
	return nil
}

// ===== 列出 MinIO bucket 中的所有对象 =====
func listObjects() error {
	input := &s3.ListObjectsV2Input{
		Bucket: aws.String(bucketName),
	}

	paginator := s3.NewListObjectsV2Paginator(s3Client, input)

	fmt.Printf("📂 Bucket '%s' 中的对象列表:\n", bucketName)
	for paginator.HasMorePages() {
		page, err := paginator.NextPage(context.TODO())
		if err != nil {
			return fmt.Errorf("列出对象失败: %v", err)
		}

		for _, obj := range page.Contents {
			fmt.Printf("- %s (大小: %d 字节)\n", *obj.Key, obj.Size)
		}
	}

	return nil
}

// ===== 主函数：按顺序调用功能（可按需注释）=====
func main() {
	// 1. 初始化 S3 客户端（推荐方式）
	err := initS3Client()
	if err != nil {
		log.Fatalf("初始化 S3 客户端失败: %v", err)
	}

	// 2. 上传文件
	err = uploadFile()
	if err != nil {
		log.Printf("上传文件出错: %v", err)
	}

	// 3. 列出 bucket 中的文件
	err = listObjects()
	if err != nil {
		log.Printf("列出文件出错: %v", err)
	}

	// 4. 下载文件
	err = downloadFile()
	if err != nil {
		log.Printf("下载文件出错: %v", err)
	}

	// 5. 删除文件
	err = deleteFile()
	if err != nil {
		log.Printf("删除文件出错: %v", err)
	}
}
